package controller;

import java.awt.Point;
import java.util.ArrayList;

import model.Collectable;
import model.Enemy;
import model.Figure;
import model.MarioObject;
import model.Model;
import model.Obstacle;
import model.Player;


public class Control extends Thread{
	
	private Model model;
	private boolean toggle = false;
	
	public Control(Model model){
		this.model = model;
	}
	
	public void run() {
		
		while(true){
			MarioObject[][][] level = model.getLevel();
			
			Player player;
			
			for(int dim =2;dim<4 ;dim++)
				for(int x=0; x < level[dim].length; x++){
					for( int y=0; y < level[dim][x].length; y++){
						
						if(level[dim][x][y] == null) continue;
						
						Figure figure = (Figure) level[dim][x][y];
						
						if(figure instanceof model.Enemy) ki((Enemy) figure); //KI implementierung
					
						if(figure.getMovingRight())
							tryMove( figure, figure.getX()+1, figure.getY()); //Speed noch ueberall einbauen/beachten
						if(figure.getMovingLeft())
							tryMove( figure, figure.getX()-1, figure.getY());
						
						if(figure.getMovingUp()){
							
							if(figure.isJumping){
								figure.jumpAmount -= 1;
								
								if(figure.jumpAmount>=0)
									tryMove( figure, figure.getX(), figure.getY()-figure.jumpAmount);

								}
						}
						
						calculateGravity(figure);
					}
				}
			
			
	
			try {
				sleep(5);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		}//While ende
	}

	
	//Collsion Detection funktion
	private boolean tryMove(Figure figure,int x, int y){
		MarioObject[][][] level = model.getLevel();
		/*
		// Statische Objekte
			boolean moveX=false;
			boolean moveY=false;
			int[] horStripes=this.getVertSprites(x);
			int[] vertStripes=this.getHorSprites(y);
			
			//System.out.println("h: "+horStripes[0]+" v: "+vertStripes[0]);
			if(horStripes[1]<0&&vertStripes[1]<0){
				if( level[0][horStripes[0]][vertStripes[0]] instanceof Obstacle ){
				}else{
					moveX=true;
					moveY=true;
				}
			}
			
			else if(horStripes[1]>=0&&vertStripes[1]<0){
				if( level[0][horStripes[0]][vertStripes[0]] instanceof Obstacle ){} else
				if( level[0][horStripes[1]][vertStripes[0]] instanceof Obstacle ){} else
				{
					moveX=true;
					moveY=true;
				}
			}
			
			else if(horStripes[1]<0&&vertStripes[1]>=0){
				if( level[0][horStripes[0]][vertStripes[0]] instanceof Obstacle ){} else
				if( level[0][horStripes[0]][vertStripes[1]] instanceof Obstacle ){} else
				{
				moveX=true;
				moveY=true;
				}
			}
				
			else if(horStripes[1]>=0&&vertStripes[1]>=0){
				if( level[0][horStripes[0]][vertStripes[0]] instanceof Obstacle ){} else
				if( level[0][horStripes[1]][vertStripes[0]] instanceof Obstacle ){} else
				if( level[0][horStripes[1]][vertStripes[1]] instanceof Obstacle ){} else
				if( level[0][horStripes[0]][vertStripes[1]] instanceof Obstacle ){} else
				{
				moveX=true;
				moveY=true;
				}
			}
			
			if(moveX==true)figure.setX(x);
			if(moveY==true)figure.setY(y);
		
		 */ 
		
		boolean move = true;
		
		//Pruefe ob überhautp im Spielfeld
		// todo: wenn unten rausfällt dann TOT!
		if( (x<0) || (x+50 >model.width) || (y<0) || (y+50 > 500) )
			return false;
		
		
		//Hindernisse, Gegner und Spieler durchgehen
		//todo: - Nur die gerade Sichtbaren durchgehen? Performance mäßig läuft das so bei mir ganz gut
		for(int dim=0;dim<4;dim++){
			for(int i = 0;i<level[dim].length;i++){
				for(int j=0;j<level[dim][i].length;j++){
					MarioObject actualObject = level[dim][i][j];
					
					if(actualObject == null) continue; //Leeres Array
					if(actualObject == figure) continue; //Der der laufen will ignorieren
					
					boolean test = false;//Testen ob man in einem anderne Objekt ist	
					
					//Gehe alle 4 Punkte der Figur durch und teste ob sich diese in einem Objekt befinden würden
					test=inQuadrat( new Point(x,y), new Point(actualObject.getX(),actualObject.getY()) );					
					if(!test) test=inQuadrat( new Point(x+50,y), new Point(actualObject.getX(),actualObject.getY()) );
					if(!test) test=inQuadrat( new Point(x,y+50), new Point(actualObject.getX(),actualObject.getY()) );
					if(!test) test=inQuadrat( new Point(x+50,y+50), new Point(actualObject.getX(),actualObject.getY()) );
					
					if(test){//Collision detected
						//Prüfen mit was Collision stattgefunden hat, damit die view/model sound abspielt,punkte addet, objekt löscht
						/*
						if(actualObject instanceof Enemy){
							//Pruefen ob draufgesprungen!
							if(jump){
								
							}else{//Nicht draufgesprungen
								model.removeLive();
							}

							move=false;
						}
						else if(actualObject instanceof Collectable){
							if(figure instanceof Player){
								actualObject = null;
								model.addCoin();
							}
						}
						else */
							move=false;//Laufen verhindern, eventuell versuchen ein px weniger zu laufen und nochmal durchgehen
					}
					
					if(!move)break; //Wenn man nicht laufen kann, restliche Objekte nicht durchgehen
					
				}			
			}
		}	
		
		
		if(move){
			figure.setX(x);
			figure.setY(y);	
		}
		
		//model.modelChanged();
		return move;
		
	}
	
	/* Funktion testet ob Punkt 1 in quadrat punkt2 ist(welches darin berechnet wird)
	//	return: 	true falls punkt in quadrat
	//				false falls nicht in quadrat
	//	todo: - 1px abstand-fehler, da wenn beide aufeinander aufliegen, haben sie die gleich koordinaten was zu true führt!
	*/
	private boolean inQuadrat(Point point1, Point point2){
		int off = 50;
		boolean inQuadrat = false;
		
		if( point1.x >= point2.x && point1.x <= point2.x+off && point1.y >= point2.y && point1.y <= point2.y+off )
			inQuadrat = true;
		
		//System.out.println("1: "+point1.x +"/"+point1.y+"\n2: "+point2.x +"/"+point2.y+"\n --"+inQuadrat);
		return inQuadrat;
	}
	
	//KI implementierung
	private void ki(Enemy enemy){
		
		//HighEnd Implementierung
		if( Math.random() >= 0.3){
			enemy.setMovingRight(false);
			enemy.setMovingLeft(true);
		}else{
			enemy.setMovingRight(true);
			enemy.setMovingLeft(false);
		}
		
	}
	
	//Gravity Funktion, 
	private void calculateGravity(Figure figure){
		
			int amount = 0;
			
			amount = 8-figure.getY()/50;
			System.out.println(amount);
			
			if(!tryMove( figure, figure.getX(),figure.getY()+amount) )
				figure.isJumping=false;
	
	}
	
	private int[] getVertSprites(int x){ 
		
		int[] i = new int[2];
		i[0]=(int)Math.floor(x/50);
		if(x%50<=0){
			i[1]=-1;
		}else{
			i[1]=i[0]+1;	
		}
		return i;
	}

	
	private  int[] getHorSprites(int y){ 
		
		int[] i = new int[2];
		i[0]=(int)Math.floor(y/50);
		if(y%50<=0){
			i[1]=-1;
		}else{
			i[1]=i[0]+1;	
		}
		return i;
	
	}

	

}
